package com.nuance.assignment.fileInfo.client.view;

import java.util.Date;

import com.google.gwt.cell.client.DateCell;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.SimplePager.TextLocation;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.CellPreviewEvent;
import com.google.gwt.view.client.CellPreviewEvent.Handler;
import com.google.gwt.view.client.RowCountChangeEvent;
import com.googlecode.gwt.charts.client.ChartLoader;
import com.googlecode.gwt.charts.client.ChartPackage;
import com.googlecode.gwt.charts.client.ColumnType;
import com.googlecode.gwt.charts.client.DataTable;
import com.googlecode.gwt.charts.client.corechart.PieChart;
import com.nuance.assignment.fileInfo.client.presenter.FileInfoPresenter;
import com.nuance.assignment.fileInfo.client.util.FileInfoConstants;
import com.nuance.assignment.fileInfo.client.util.FileInfoMessages;
import com.nuance.assignment.fileInfo.shared.Constants;
import com.nuance.assignment.fileInfo.shared.FileDTO;

/**
 * The view in MVP pattern 
 * 
 * @author parag
 *
 */
public class FileInfoView extends Composite implements FileInfoPresenter.View {

	private PieChart pieChart;
	private final VerticalPanel verticalPanel = new VerticalPanel();
	private final FileInfoSuggestOracle fileInfoSuggestOracle;
	private final SuggestBox suggestBox;
	private final Button submitButton = new Button();
	private final CellTable<FileDTO> cellTable = new CellTable<>();
	private final FileInfoMessages fileInfoMessages;
	private final DateTimeFormat dateTimeFormat;
	private final FileInfoConstants fileInfoConstants;
	
	public FileInfoView(FileInfoMessages messages, 
			FileInfoConstants constants,
			DateTimeFormat dateTimeFormat) {
		this.fileInfoMessages = messages;
		this.fileInfoConstants = constants;
		this.dateTimeFormat = dateTimeFormat;
		this.fileInfoSuggestOracle = new FileInfoSuggestOracle(constants);
		this.suggestBox = new SuggestBox(fileInfoSuggestOracle);
		
		verticalPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		verticalPanel.setSpacing(30);
		verticalPanel.add(createInputSection());
		verticalPanel.add(createTable());
		
		initWidget(verticalPanel);
	}

	private Widget createInputSection() {
		HorizontalPanel horizontalPanel = new HorizontalPanel();
		horizontalPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		horizontalPanel.setSpacing(10);
		horizontalPanel.add(createSuggestBox());
		horizontalPanel.add(createSubmitButton());
		return horizontalPanel;
	}
	
	
	private Widget createSuggestBox(){
		suggestBox.setWidth("50em");
		suggestBox.addSelectionHandler(new SelectionHandler<Suggestion>(){
			@Override
			public void onSelection(SelectionEvent<Suggestion> event) {
				suggestBox.setText(event.getSelectedItem().getReplacementString());
				refreshData();
			}
		});
		return suggestBox;
	}
	
	private Widget createSubmitButton(){
		submitButton.setText(fileInfoMessages.submit());
		submitButton.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				refreshData();
			}
		});
		return submitButton;
	}
	
	private SimplePager createPager(){
		SimplePager.Resources pagerResources = GWT.create(SimplePager.Resources.class);
		SimplePager pager = new SimplePager(TextLocation.CENTER, pagerResources, false, 0,true);
		pager.setDisplay(cellTable);
		pager.setPageSize(fileInfoConstants.tablePageSize());
		return pager;
	}

	private Widget createTable() {
		VerticalPanel verticalPanel = new VerticalPanel();
		verticalPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
		verticalPanel.add(cellTable);
		verticalPanel.add(createPager());
		
		cellTable.setEmptyTableWidget(new Label(fileInfoMessages.emptyTable()));
		cellTable.setAutoHeaderRefreshDisabled(true);
		cellTable.setAutoFooterRefreshDisabled(true);
		cellTable.setPageSize(fileInfoConstants.tablePageSize());
		cellTable.addColumnSortHandler(new ColumnSortEvent.Handler() {
			@Override
			public void onColumnSort(ColumnSortEvent event) {
				refreshData();
			}
		});
		cellTable.addCellPreviewHandler(new Handler<FileDTO>(){
			@Override
			public void onCellPreview(CellPreviewEvent<FileDTO> event) {
				if(BrowserEvents.CLICK.equalsIgnoreCase(event.getNativeEvent().getType())
						&& event.getValue().isDirectory()){
					suggestBox.setText(event.getValue().getAbsolutePath());
					refreshData();
				}
			}
		});
		cellTable.addRowCountChangeHandler(new RowCountChangeEvent.Handler(){
			@Override
			public void onRowCountChange(RowCountChangeEvent event) {
				redrawChart();
			}
		});
		
		
		TextColumn<FileDTO> nameColumn = new TextColumn<FileDTO>() {
			@Override
			public String getValue(FileDTO object) {
				return object.getName();
			}
		};
		nameColumn.setSortable(true);
		cellTable.addColumn(nameColumn, fileInfoMessages.name());
		nameColumn.setDataStoreName(Constants.NAME);
		
		
		TextColumn<FileDTO> pathColumn = new TextColumn<FileDTO>() {
			@Override
			public String getValue(FileDTO object) {
				return object.getAbsolutePath();
			}
		};
		pathColumn.setSortable(true);
		cellTable.addColumn(pathColumn, fileInfoMessages.path());
		pathColumn.setDataStoreName(Constants.PATH);

		TextColumn<FileDTO> lengthColumn = new TextColumn<FileDTO>() {
			@Override
			public String getValue(FileDTO object) {
				return String.valueOf(object.getLength());
			}
		};
		lengthColumn.setSortable(true);
		cellTable.addColumn(lengthColumn, fileInfoMessages.length());
		lengthColumn.setDataStoreName(Constants.LENGTH);

		TextColumn<FileDTO> canReadColumn = new TextColumn<FileDTO>() {
			@Override
			public String getValue(FileDTO object) {
				return asString(object.isCanRead());
			}
		};
		canReadColumn.setSortable(true);
		cellTable.addColumn(canReadColumn, fileInfoMessages.canRead());
		canReadColumn.setDataStoreName(Constants.CAN_READ);

		TextColumn<FileDTO> canWriteColumn = new TextColumn<FileDTO>() {
			@Override
			public String getValue(FileDTO object) {
				return asString(object.isCanWrite());
			}
		};
		canWriteColumn.setSortable(true);
		cellTable.addColumn(canWriteColumn, fileInfoMessages.canWrite());
		canWriteColumn.setDataStoreName(Constants.CAN_WRITE);

		TextColumn<FileDTO> canExecuteColumn = new TextColumn<FileDTO>() {
			@Override
			public String getValue(FileDTO object) {
				return asString(object.isCanExecute());
			}
		};
		canExecuteColumn.setSortable(true);
		cellTable.addColumn(canExecuteColumn, fileInfoMessages.canExecute());
		canExecuteColumn.setDataStoreName(Constants.CAN_EXECUTE);

		TextColumn<FileDTO> isFileColumn = new TextColumn<FileDTO>() {
			@Override
			public String getValue(FileDTO object) {
				return asString(object.isFile());
			}
		};
		isFileColumn.setSortable(true);
		cellTable.addColumn(isFileColumn, fileInfoMessages.isFile());
		isFileColumn.setDataStoreName(Constants.IS_FILE);

		TextColumn<FileDTO> isDirectoryColumn = new TextColumn<FileDTO>() {
			@Override
			public String getValue(FileDTO object) {
				return asString(object.isDirectory());
			}
		};
		isDirectoryColumn.setSortable(true);
		cellTable.addColumn(isDirectoryColumn, fileInfoMessages.isDirectory());
		isDirectoryColumn.setDataStoreName(Constants.IS_DIRECTORY);
		
		TextColumn<FileDTO> isHiddenColumn = new TextColumn<FileDTO>() {
			@Override
			public String getValue(FileDTO object) {
				return asString(object.isHidden());
			}
		};
		isHiddenColumn.setSortable(true);
		cellTable.addColumn(isHiddenColumn, fileInfoMessages.isHidden());
		isHiddenColumn.setDataStoreName(Constants.IS_HIDDEN);
		
		DateCell dateCell = new DateCell(dateTimeFormat);
		Column<FileDTO, Date> lastModifiedColumn = new Column<FileDTO, Date>(dateCell) {
			@Override
			public Date getValue(FileDTO object) {
				return new Date(object.getLastModified());
			}
		};
		lastModifiedColumn.setSortable(true);
		cellTable.addColumn(lastModifiedColumn, fileInfoMessages.lastModified());
		lastModifiedColumn.setDataStoreName(Constants.LAST_MODIFIED);

		return verticalPanel;
	}
	
	public void refreshData(){
		cellTable.setVisibleRangeAndClearData(cellTable.getVisibleRange(), true);
	}
	
	private String asString(boolean value){
		return value ? fileInfoMessages.yes() : fileInfoMessages.no();
	}
	
	public void setFileInfoDataProvider(FileInfoDataProvider fileInfoDataProvider) {
		fileInfoDataProvider.setHasText(suggestBox);
		fileInfoDataProvider.addDataDisplay(cellTable);
	}

	private void redrawChart(){
		ChartLoader chartLoader = new ChartLoader(ChartPackage.CORECHART);
		 chartLoader.loadApi(new Runnable() {
		        @Override
		        public void run() {
		        	if(null == pieChart){
		        		pieChart = new PieChart();
		        		verticalPanel.add(pieChart);
		        	}
		        	int count = cellTable.getVisibleItemCount();
					if(count < fileInfoConstants.chartMaxEntries()){
						DataTable dataTable = DataTable.create();
						dataTable.addColumn(ColumnType.STRING, fileInfoMessages.name());
						dataTable.addColumn(ColumnType.NUMBER, fileInfoMessages.length());
						dataTable.addRows(count);
						for(int index = 0; index < count; index++){
							FileDTO fileDTO = cellTable.getVisibleItems().get(index);
							dataTable.setValue(index, 0, fileDTO.getName());
							dataTable.setValue(index, 1, fileDTO.getLength());
						}
						pieChart.draw(dataTable);
						pieChart.setVisible(true);
					}else{
						pieChart.setVisible(false);
					}
		        }
		 });

	}
	
}
